package com.olymtech.jbricks.threadpool.alarm;

import com.olymtech.jbricks.threadpool.DynamicThreadPoolManager;
import com.olymtech.jbricks.threadpool.config.DynamicThreadPoolProperties;
import com.olymtech.jbricks.threadpool.config.ThreadPoolProperties;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.PostConstruct;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author haoting.wang
 * @date 2020/10/15 9:38 上午
 **/
public class DynamicThreadPoolAlarm {


    @Autowired
    private DynamicThreadPoolProperties dynamicThreadPoolProperties;

    @Autowired
    private DynamicThreadPoolManager dynamicThreadPoolManager;

    private volatile boolean update = false;

    @PostConstruct
    public void init() {

        new Thread(() -> {
            while (true) {

                while (!update) {

                    dynamicThreadPoolProperties.getExecutors().forEach(executor -> {
                        String threadPoolName = executor.getThreadPoolName();

                        ThreadPoolExecutor threadPoolExecutor = dynamicThreadPoolManager.getThreadPoolExecutor(threadPoolName);

                        int size = threadPoolExecutor.getQueue().size();
                        int queueCapacityThreshold = executor.getQueueCapacityThreshold();

                        if (queueCapacityThreshold < size) {
                            sendQueueCapacityThresholdAlarmMessage(executor, size);
                        }
                        AtomicLong rejectCount = dynamicThreadPoolManager.getRejectCount(threadPoolName);
                        if (rejectCount != null && rejectCount.get() > 0) {
                            sendRejectAlarmMessage(rejectCount.get(), executor);
                            // 清空拒绝数据
                            dynamicThreadPoolManager.clearRejectCount(threadPoolName);
                        }

                    });
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

        }).start();
    }
    public void setUpdate(boolean update) {
        this.update = update;
    }

    private void sendRejectAlarmMessage(long rejectCount, ThreadPoolProperties prop) {
        AlarmMessage alarmMessage = AlarmMessage.builder()
                .alarmName("rejectCount")
                .apiUrl(dynamicThreadPoolProperties.getAlarmApiUrl())
                .message(getRejectCountMessage(rejectCount, prop))
                .alarmTimeInterval(dynamicThreadPoolProperties.getAlarmTimeInterval())
                .build();

        AlarmManager.sendAlarmMessage(alarmMessage);

    }


    private void sendQueueCapacityThresholdAlarmMessage(ThreadPoolProperties prop, int taskCount) {
        AlarmMessage alarmMessage = AlarmMessage.builder()
                .alarmName("queueCapacityThreshold")
                .apiUrl(dynamicThreadPoolProperties.getAlarmApiUrl())
                .message(getQueueCapacityThresholdMessage(prop, taskCount))
                .alarmTimeInterval(dynamicThreadPoolProperties.getAlarmTimeInterval())
                .build();

        AlarmManager.sendAlarmMessage(alarmMessage);

    }

    private String getQueueCapacityThresholdMessage(ThreadPoolProperties prop, int taskCount) {
        return getALarmMessage("线程池出现任务堆积情况,队列容量:" + prop.getQueueCapacity() + ",等待执行任务数量:" + taskCount, prop);
    }

    private String getRejectCountMessage(long rejectCount, ThreadPoolProperties prop) {
        return getALarmMessage("线程池中出现RejectedExecutionException异常" + rejectCount + "次", prop);
    }

    private String getALarmMessage(String reason, ThreadPoolProperties prop) {
        StringBuilder content = new StringBuilder();
        content.append("告警应用:").append(dynamicThreadPoolProperties.getApplicationName()).append("\n");
        content.append("线程池名称:").append(prop.getThreadPoolName()).append("\n");
        content.append("告警原因:").append(reason).append("\n");
        content.append("参数信息:").append(formatThreadPoolParam(prop));
        content.append("业务负责人:").append(dynamicThreadPoolProperties.getOwner()).append("\n");
        content.append("告警间隔:").append(dynamicThreadPoolProperties.getAlarmTimeInterval()).append("分钟\n");
        return content.toString();
    }

    private String formatThreadPoolParam(ThreadPoolProperties prop) {
        String content = prop.toString();

        return content;
    }
}
